#include "Mips.h"

/* Instructions Selection */
VarDes_ *varList = NULL; //list of variables.

/* Registers Allocation */
RegDes_ regs[32];
int reg_cur = 0;

char *regsAlias[] = {
	"$zero",
	"$at",
	"$v0", "$v1",
	"$a0", "$a1", "$a2", "a3",
	"$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
	"$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
	"$t8", "$t9",
	"$k0", "$k1",
	"$gp", "$sp", "$fp", "$ra"};

/* Stack Management */
int offset_sp = 0;
int param_cur = 0;
int arg_cur = 0;
const int stackSize = 128;

/*----- Variables Handle -----*/
//push new variable into the tail of the list
void addVar(VarDes_ *var)
{
	assert(var != NULL);
	if (varList == NULL)
	{
		varList = var;
		varList->next = var->next = NULL;
	}
	else
	{
		var->next = NULL;
		VarDes_ *ptr = varList;
		while (ptr->next != NULL)
			ptr = ptr->next;
		ptr->next = var;
	}
	return;
}
//obtain the location of the variable by its name
VarDes_ *locateVar(char *name)
{
	VarDes_ *ptr = varList;
	while (ptr != NULL)
	{
		if (strcmp(ptr->name, name) == 0)
			break;
		else
			ptr = ptr->next;
	}
	return ptr;
}
//free the list of variables
void freeVarList()
{
	VarDes_ *ptr = varList;
	while (ptr != NULL)
	{
		varList = varList->next;
		free(ptr);
		ptr = varList;
	}
	return;
}

/*----- Allocate Registers -----*/
//store
void swReg(int index, FILE *fp)
{
	char str[64] = {'\0'};
	VarDes_ *var = regs[index].var;
	sprintf(str, "\tsw %s, %d($fp)\n", regs[index].name, var->offset);
	fputs(str, fp);
}
//load
void lwReg(int index, VarDes_ *var, FILE *fp)
{
	char str[64] = {'\0'};
	regs[index].var = var;
	sprintf(str, "\tlw %s, %d($fp)\n", regs[index].name, var->offset);
	fputs(str, fp);
}
//initiate
void initRegs()
{	
	for (int i = 0; i < 32; i++)
	{
		regs[i].name = regsAlias[i];
		regs[i].var = NULL;
	}
}
//allocate
int allocateReg(Operand item, FILE *fp)
{
	char *name = NULL;
	if (item->kind == TEMPVAR)
	{
		name = (char *)malloc(64);
		memset(name, 0, sizeof(name));
		sprintf(name, "t%d", item->var_no);
	}
	else if (item->kind == VARIABLE)
	{
		name = item->value;
	}
	//TODO: TADDRESS && VADDRESS
	int i = reg_cur;
	i += REG_TPR; //$8~$15
	reg_cur++;
	reg_cur = reg_cur % 8; //8: $8~$15
	VarDes_ *var = locateVar(name);
	if (var != NULL)
	{
		var->regNo = i;
		regs[i].var = NULL;
		lwReg(i, var, fp);
	}
	else
	{
		var = malloc(sizeof(VarDes_));
		var->name = name;
		offset_sp -= 4;
		var->offset = offset_sp;
		addVar(var);
		var->regNo = i;
		regs[i].var = var;
	}
	return i;
}

/*----- Instructions Selection -----*/

void labelHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	sprintf(str, "label%d:\n", interCode->sinop.op->var_no);
	fputs(str, fp);

	fclose(fp);
}

void functionHandle(InterCode interCode, char *fileName)
{
	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	sprintf(str, "%s:\n\tsubu $sp, $sp, 4\n\tsw $fp, 0($sp)\n\tmove $fp, $sp\n\tsubu $sp, $sp, %d\n", interCode->sinop.op->value, stackSize);
	fputs(str, fp);
	offset_sp = 0;
	param_cur = 0;

	fclose(fp);
}

void assignHandle(InterCode interCode, char *fileName)
{
	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};

	Operand left_op = interCode->assign.left;
	Operand right_op = interCode->assign.right;

	int x, y;
	if ((left_op->kind == VARIABLE) || (left_op->kind == TEMPVAR))
	{
		if (right_op->kind == CONSTANT)
		{
			x = allocateReg(left_op, fp);
			sprintf(str, "\tli %s, %s\n", regs[x].name, right_op->value);
			fputs(str, fp);
		}
		else if ((right_op->kind == VARIABLE) || (right_op->kind == TEMPVAR))
		{
			x = allocateReg(left_op, fp);
			y = allocateReg(right_op, fp);
			sprintf(str, "\tmove %s, %s\n", regs[x].name, regs[y].name);
			fputs(str, fp);
		}
		else if (right_op->kind == ADDRESS)
		{
			x = allocateReg(left_op, fp);
			y = allocateReg(right_op, fp);
			sprintf(str, "\tlw %s, 0(%s)\n", regs[x].name, regs[y].name);
			fputs(str, fp);
		}
	}
	else if (left_op->kind == ADDRESS)
	{
		if (right_op->kind == CONSTANT)
		{
			x = allocateReg(left_op, fp);
			sprintf(str, "\tli $s3, %s\n\tsw $s3 0(%s)\n", right_op->value, regs[x].name);
			fputs(str, fp);
		}
		else if ((right_op->kind == TEMPVAR) || (right_op->kind == VARIABLE))
		{
			x = allocateReg(left_op, fp);
			y = allocateReg(right_op, fp);
			sprintf(str, "\tsw %s, 0(%s)\n", regs[y].name, regs[x].name);
			fputs(str, fp);
		}
	}
	swReg(x, fp);

	fclose(fp);
}

// + - * /
void operationHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};

	Operand left_op = interCode->binop.op1;
	Operand right_op = interCode->binop.op2;
	Operand result = interCode->binop.result;

	int a, b, c;

	if ((left_op->kind == TEMPVAR || left_op->kind == VARIABLE) && (right_op->kind == TEMPVAR || right_op->kind == VARIABLE))
	{
		a = allocateReg(result, fp);
		b = allocateReg(left_op, fp);
		c = allocateReg(right_op, fp);
		if (interCode->kind == IR_ADD)
		{ // +
			sprintf(str, "\tadd %s, %s, %s\n", regs[a].name, regs[b].name, regs[c].name);
		}
		else if (interCode->kind == IR_SUB)
		{ // -
			sprintf(str, "\tsub %s, %s, %s\n", regs[a].name, regs[b].name, regs[c].name);
		}
		else if (interCode->kind == IR_MUL)
		{ // *
			sprintf(str, "\tmul %s, %s, %s\n", regs[a].name, regs[b].name, regs[c].name);
		}
		else if (interCode->kind == IR_DIV)
		{ // /
			sprintf(str, "\tdiv %s, %s\n\tmflo %s\n", regs[b].name, regs[c].name, regs[a].name);
		}
		else
		{
			printf("ERROR: current operation is illegal.\n");
			return;
		}
		fputs(str, fp);
	}
	else if ((left_op->kind == CONSTANT) && (right_op->kind == TEMPVAR || right_op->kind == VARIABLE))
	{
		a = allocateReg(result, fp);
		b = allocateReg(right_op, fp);
		if (interCode->kind == IR_ADD)
		{ // +
			sprintf(str, "\taddi %s, %s, %s\n", regs[a].name, regs[b].name, left_op->value);
		}
		else if (interCode->kind == IR_SUB)
		{ // -
			sprintf(str, "\taddi %s, %s, -%s\n", regs[a].name, regs[b].name, left_op->value);
		}
		else
		{
			//TODO: *  / see testcase4
			printf("ERROR: current operation is illegal.\n");
			assert(0);
		}
		fputs(str, fp);
	}
	else if ((right_op->kind == CONSTANT) && (left_op->kind == TEMPVAR || left_op->kind == VARIABLE))
	{
		a = allocateReg(result, fp);
		b = allocateReg(left_op, fp);
		if (interCode->kind == IR_ADD)
		{ // +
			sprintf(str, "\taddi %s, %s, %s\n", regs[a].name, regs[b].name, right_op->value);
		}
		else if (interCode->kind == IR_SUB)
		{ // -
			sprintf(str, "\taddi %s, %s, -%s\n", regs[a].name, regs[b].name, right_op->value);
		}
		else
		{
			printf("ERROR: current operation is illegal.\n");
			assert(0);
			return;
		}
		fputs(str, fp);
	}

	swReg(a, fp);

	fclose(fp);
}

void addressHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	Operand left_op = interCode->assign.left;
	Operand right_op = interCode->assign.right;
	VarDes_ *head = NULL;
	if (right_op->kind == VARIABLE)
	{
		head = locateVar(right_op->value);
	}
	else if (right_op->kind == TEMPVAR)
	{
		char *arrayName = malloc(32);
		memset(arrayName, 0, sizeof(arrayName));
		sprintf(arrayName, "t%d", right_op->var_no);
		head = locateVar(arrayName);
	}

	assert(head != NULL);

	int x = allocateReg(left_op, fp);
	char str[256] = {'\0'};
	sprintf(str, "\tlw %s, %d($fp)\n", regs[x].name, head->offset);
	fputs(str, fp);
	swReg(x, fp);

	fclose(fp);
}

void gotoHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	sprintf(str, "\tj label%d\n", interCode->sinop.op->var_no);
	fputs(str, fp);

	fclose(fp);
}

void ifgotoHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	Operand left_op = interCode->triop.x;
	Operand right_op = interCode->triop.y;
	Operand label = interCode->triop.label;
	char *op = interCode->triop.op;

	if (left_op->kind != CONSTANT && right_op->kind != CONSTANT)
	{
		int x = allocateReg(left_op, fp);
		int y = allocateReg(right_op, fp);
		if (strcmp(op, "==") == 0)
		{ // x == y
			sprintf(str, "\tbeq %s, %s, label%d\n", regs[x].name, regs[y].name, label->var_no);
		}
		else if (strcmp(op, "!=") == 0)
		{ // x != y
			sprintf(str, "\tbne %s, %s, label%d\n", regs[x].name, regs[y].name, label->var_no);
		}
		else if (strcmp(op, ">") == 0)
		{ // x > y
			sprintf(str, "\tbgt %s, %s, label%d\n", regs[x].name, regs[y].name, label->var_no);
		}
		else if (strcmp(op, "<") == 0)
		{ // x < y
			sprintf(str, "\tblt %s, %s, label%d\n", regs[x].name, regs[y].name, label->var_no);
		}
		else if (strcmp(op, ">=") == 0)
		{ // x >= y
			sprintf(str, "\tbge %s, %s, label%d\n", regs[x].name, regs[y].name, label->var_no);
		}
		else if (strcmp(op, "<=") == 0)
		{ // x <= y
			sprintf(str, "\tble %s, %s, label%d\n", regs[x].name, regs[y].name, label->var_no);
		}
		else
		{
			printf("ERROR: current operation is illegal.\n");
			return;
		}
	}
	else if (left_op->kind == CONSTANT && right_op->kind != CONSTANT)
	{ // TODO: errors may happen here, load constant to reg.
		int y = allocateReg(right_op, fp);
		if (strcmp(op, "==") == 0)
		{
			sprintf(str, "\tbeq %s, %s, label%d\n", regs[y].name, left_op->value, label->var_no);
		}
		else if (strcmp(op, "!=") == 0)
		{
			sprintf(str, "\tbne %s, %s, label%d\n", regs[y].name, left_op->value, label->var_no);
		}
		else if (strcmp(op, ">") == 0)
		{
			sprintf(str, "\tblt %s, %s, label%d\n", regs[y].name, left_op->value, label->var_no);
		}
		else if (strcmp(op, "<") == 0)
		{
			sprintf(str, "\tbgt %s, %s, label%d\n", regs[y].name, left_op->value, label->var_no);
		}
		else if (strcmp(op, ">=") == 0)
		{
			sprintf(str, "\tble %s, %s, label%d\n", regs[y].name, left_op->value, label->var_no);
		}
		else if (strcmp(op, "<=") == 0)
		{
			sprintf(str, "\tbge %s, %s, label%d\n", regs[y].name, left_op->value, label->var_no);
		}
	}
	else if (left_op->kind != CONSTANT && right_op->kind == CONSTANT)
	{
		int x = allocateReg(left_op, fp);
		if (strcmp(op, "==") == 0)
		{
			sprintf(str, "\tbeq %s, %s, label%d\n", regs[x].name, right_op->value, label->var_no);
		}
		else if (strcmp(op, "!=") == 0)
		{
			sprintf(str, "\tbne %s, %s, label%d\n", regs[x].name, right_op->value, label->var_no);
		}
		else if (strcmp(op, ">") == 0)
		{
			sprintf(str, "\tbgt %s, %s, label%d\n", regs[x].name, right_op->value, label->var_no);
		}
		else if (strcmp(op, "<") == 0)
		{
			sprintf(str, "\tblt %s, %s, label%d\n", regs[x].name, right_op->value, label->var_no);
		}
		else if (strcmp(op, ">=") == 0)
		{
			sprintf(str, "\tbge %s, %s, label%d\n", regs[x].name, right_op->value, label->var_no);
		}
		else if (strcmp(op, "<=") == 0)
		{
			sprintf(str, "\tble %s, %s, label%d\n", regs[x].name, right_op->value, label->var_no);
		}
	}
	else if (left_op->kind == CONSTANT && right_op->kind == CONSTANT)
	{
		//be optimized or omitted???
	}
	else
	{
		printf("ERROR: current operation is illegal.\n");
		assert(0);
		return;
	}

	fputs(str, fp);

	fclose(fp);
}

void returnHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	Operand op = interCode->sinop.op;
	if (op->kind != CONSTANT)
	{
		int x = allocateReg(op, fp);
		sprintf(str, "\tmove $v0, %s\n\taddi $sp, $sp, %d\n\tlw $fp, 0($sp)\n\taddi $sp, $sp, 4\n\tjr $ra\n", regs[x].name, stackSize);
	}
	else
	{
		sprintf(str, "\tmove $v0, $%s\n\taddi $sp, $sp, %d\n\tlw $fp, 0($sp)\n\taddi $sp, $sp, 4\n\tjr $ra\n", op->value, stackSize);
	}

	fputs(str, fp);

	fclose(fp);
}

void decHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	VarDes_ *head = malloc(sizeof(VarDes_));
	offset_sp -= 4;
	head->offset = offset_sp;
	offset_sp -= interCode->dec.size;
	if (interCode->dec.op->kind == VARIABLE)
	{
		head->name = interCode->dec.op->value;
	}
	else if (interCode->dec.op->kind == TEMPVAR)
	{
		char *arrayName = malloc(32);
		memset(arrayName, 0, sizeof(arrayName));
		sprintf(arrayName, "t%d", interCode->dec.op->var_no);
		head->name = arrayName;
	}
	addVar(head);

	char str[256] = {'\0'};
	sprintf(str, "\taddi $s1, $fp, %d\n\tsw $s1, %d($fp)\n", offset_sp, head->offset);
	fputs(str, fp);

	fclose(fp);
}

void argHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	Operand op = interCode->sinop.op;
	VarDes_ *arg = NULL;
	if (op->kind == TEMPVAR)
	{
		char argName[20];
		memset(argName, 0, 20);
		sprintf(argName, "t%d", op->var_no);
		arg = locateVar(argName);
	}
	else if (op->kind == VARIABLE)
	{
		arg = locateVar(op->value);
	}
	else
	{
		printf("ERROR: current argument is illegal.\n");
		return;
	}

	assert(arg != NULL);

	if (arg_cur < 4)
	{
		sprintf(str, "\tlw $a%d, %d($fp)\n", arg_cur, arg->offset);
	}
	else
	{
		sprintf(str, "\tlw $s0, %d($fp)\n\tsubu $sp, $sp, 4\n\tlw $s0, 0($sp)\n", arg->offset);
	}

	fputs(str, fp);
	arg_cur++;
	if (interCode->next == NULL || interCode->next->kind != IR_ARG)
	{
		arg_cur = 0;
	}

	fclose(fp);
}

void callHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	fputs("\tsubu $sp, $sp, 4\n", fp);
	fputs("\tsw $ra, 0($sp)\n", fp);

	Operand op = interCode->assign.left;
	Operand func = interCode->assign.right;

	int x = allocateReg(op, fp);

	char str[256] = {'\0'};
	sprintf(str, "\tjal %s\n\tmove %s, $v0\n", func->value, regs[x].name);
	fputs(str, fp);

	swReg(x, fp);
	fputs("\tlw $ra, 0($sp)\n", fp);
	fputs("\taddi $sp, $sp, 4\n", fp);

	arg_cur = 0;

	fclose(fp);
}

void paramHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	char str[256] = {'\0'};
	VarDes_ *param = malloc(sizeof(VarDes_));
	param->name = interCode->sinop.op->value;
	offset_sp -= 4;
	param->offset = offset_sp;
	addVar(param);
	if (param_cur < 4)
	{
		sprintf(str, "\tsw $a%d, %d($fp)\n", param_cur, param->offset);
	}
	else
	{
		sprintf(str, "\tlw $a0, %d($fp)\n\tsw $a0, %d($fp)\n", (param_cur - 2) * 4, param->offset);
	}
	fputs(str, fp);
	param_cur++;

	fclose(fp);
}

void readHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	fputs("\tsubu $sp, $sp, 4\n", fp);
	fputs("\tsw $ra, 0($sp)\n", fp);

	int x = allocateReg(interCode->sinop.op, fp);
	char str[256] = {'\0'};
	sprintf(str, "\tjal read\n\tmove %s, $v0\n", regs[x].name);
	fputs(str, fp);
	swReg(x, fp);

	fputs("\tlw $ra, 0($sp)\n", fp);
	fputs("\taddi $sp, $sp, 4\n", fp);

	fclose(fp);
}

void writeHandle(InterCode interCode, char *fileName)
{

	assert(interCode != NULL);

	FILE *fp;
	fp = fopen(fileName, "a+");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	fputs("\tsubu $sp, $sp, 4\n", fp);
	fputs("\tsw $ra, 0($sp)\n", fp);

	char str[256] = {'\0'};
	int r = allocateReg(interCode->sinop.op, fp);
	if (interCode->sinop.op->kind == TEMPVAR || interCode->sinop.op->kind == VARIABLE)
	{
		sprintf(str, "\tmove $a0, %s\n\tjal write\n", regs[r].name);
	}
	else if (interCode->sinop.op->kind == ADDRESS)
	{
		sprintf(str, "\tlw $a0, 0(%s)\n\tjal write\n", regs[r].name);
	}
	fputs(str, fp);
	swReg(r, fp);

	fputs("\tlw $ra, 0($sp)\n", fp);
	fputs("\taddi $sp, $sp, 4\n", fp);

	fclose(fp);
}

/*-----Print(Generate) MIPS Code -----*/
void printMipsBlock(InterCode interCode, char *fileName)
{
	assert(interCode != NULL);

	switch (interCode->kind)
	{
	case IR_LABEL:
		labelHandle(interCode, fileName);
		break;
	case IR_FUNC:
		functionHandle(interCode, fileName);
		break;
	case IR_ASSIGN:
		assignHandle(interCode, fileName);
		break;
	case IR_ADD:
	case IR_SUB:
	case IR_MUL:
	case IR_DIV:
		operationHandle(interCode, fileName);
		break;

	case IR_ADDR:
		addressHandle(interCode, fileName);
		break;
	case IR_DEREF_R:
		addressHandle(interCode, fileName);
		break;
	case IR_DEREF_L:
		addressHandle(interCode, fileName);
		break;

	case IR_READ:
		readHandle(interCode, fileName);
		break;
	case IR_WRITE:
		writeHandle(interCode, fileName);
		break;
		
	case IR_GOTO:
		gotoHandle(interCode, fileName);
		break;
	case IR_IFGOTO:
		ifgotoHandle(interCode, fileName);
		break;
	case IR_RETURN:
		returnHandle(interCode, fileName);
		break;
	case IR_DEC:
		decHandle(interCode, fileName);
		break;
	case IR_ARG:
		argHandle(interCode, fileName);
		break;
	case IR_CALL:
		callHandle(interCode, fileName);
		break;
	case IR_PARAM:
		paramHandle(interCode, fileName);
		break;

	default:
		printf("ERROR: current kind is illegal.\n");
		assert(0);
		return;
	}
}

void printMips(char *fileName)
{

	FILE *fp;
	fp = fopen(fileName, "w");
	if (fp == NULL)
	{
		printf("ERROR: fail to open the file \"%s\".", fileName);
		return;
	}

	initRegs();
	fputs(".data\n", fp);
	fputs("_prompt: .asciiz \"Enter an integer:\"\n", fp);
	fputs("_ret: .asciiz \"\\n\"\n", fp);
	fputs(".globl main\n", fp);
	fputs(".text\n", fp);

	fputs("read:\n", fp);
	fputs("\tli $v0, 4\n", fp);
	fputs("\tla $a0, _prompt\n", fp);
	fputs("\tsyscall\n", fp);
	fputs("\tli $v0, 5\n", fp);
	fputs("\tsyscall\n", fp);
	fputs("\tjr $ra\n\n", fp);

	fputs("write:\n", fp);
	fputs("\tli $v0, 1\n", fp);
	fputs("\tsyscall\n", fp);
	fputs("\tli $v0, 4\n", fp);
	fputs("\tla $a0, _ret\n", fp);
	fputs("\tsyscall\n", fp);
	fputs("\tmove $v0, $0\n", fp);
	fputs("\tjr $ra\n\n", fp);

	fclose(fp);

	for (InterCode itr = code_head; itr != NULL; itr = itr->next)
		printMipsBlock(itr, fileName);
}
